package cn.edu.cuit.filter;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import cn.edu.cuit.filter.CharacterRequest;

/**
 * @author fhzheng
 * <h1> 字符过滤器 </h1>
 * <li> 防止请求中的中文乱码现象，统一用utf-8编码格式
 * <li> 防止响应中的中文乱码现象，统一用utf-8编码格式
 * <li> 对于请求的参数，专门编写了转码方法，即启用了内部类的方法
 * <li> 内部类专门处理get方式的请求的参数
 */
public class CharacterFilter implements Filter {
	
	// 过滤器调用的计数器
	static Integer filterCallCount = 0;
	
	
	/**
	 * <li> 生命周期函数：初始化
	 */
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	/**
	 * <li> 生命周期函数：过滤器
	 */
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		
		// 调用计数
		CharacterFilter.filterCallCount++;
		
		// 强转为带协议的request和response对象
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		// 拦截所有的请求 解决全站中文乱码
		// 指定 request 和 response 的编码
		request.setCharacterEncoding("utf-8"); // 只对消息体有效
		response.setContentType("text/html;charset=utf-8");
		System.out.println("字符过滤器在此完成对请求和响应的编码方式设置");
		// 对request进行包装过滤，全部转为utf-8编码
		CharacterRequest characterRequest = new CharacterRequest(request);
		System.out.println("字符过滤器开始过滤请求");
		// 字符过滤器放行
		chain.doFilter(characterRequest, response);
		System.out.println("======字符过滤器第"+CharacterFilter.filterCallCount+"次过滤完工======");
	}

	/**
	 * <li> 生命周期函数：销毁
	 */
	public void destroy() {
	}
}

// 继承 默认包装类HttpServletRequestWrapper
/**
 * @author fhzheng
 * <h1> 内部类 </h1>
 * <li> 处理字符请求，将请求统一转换为utf-8编码
 */
class CharacterRequest extends HttpServletRequestWrapper {
	
	private HttpServletRequest request;

	public CharacterRequest(HttpServletRequest request) {
		super(request);
		this.request = request;
	}

	// 子类继承父类一定会覆写一些方法，此处用于重写getParamter()方法
	public String getParameter(String name) {
		// 调用被包装对象的getParameter()方法，获得请求参数
		String value = super.getParameter(name);
		if (value == null)
			return null;	// 没有参数则不用做动作
		// 判断请求方式
		String method = super.getMethod();
		// 只对get方式完成动作
		if ("get".equalsIgnoreCase(method)) {
			try {
				System.out.println("过滤器调用内部类方法完成get方式请求参数的过滤功能");
				// 一定要注意，传进来的字符本身是什么编码
				value = new String(value.getBytes(), "utf-8");
				// value = new String(value.getBytes("iso-8859-1"), "utf-8");
				// value = new String(value.getBytes("iso-8859-1"), "GBK");
			} catch (UnsupportedEncodingException e) {
				// 抛出一个运行时异常
				throw new RuntimeException(e);
			}
		}
		// 解决乱码后返回结果
		return value;
	}
}